﻿using System.Data;
using DotNetCore.CAP;
using Shop.Core.Helper;
using Shop.Core.Repository;
using Shop.Core.Share;
using Shop.IServices.Admin;
using Shop.Model.Dto.Admin.Order;
using Shop.Model.Entity.Goo;
using Shop.Model.Entity.Jur;
using Shop.Model.Entity.Order;
using Shop.Model.Entity.System;
using Shop.Model.Entity.Use;
using Shop.Model.View.Admin.Order;
using SqlSugar;

namespace Shop.Services.Admin;

public class OrdService: AbstractService, IOrdService
{
    private readonly RepositoryBase<UseUser> _userRepository;
    private readonly RepositoryBase<Orders> _orderRepository;
    private readonly RepositoryBase<UserWalletLog> _walletLogRepository;
    private readonly RepositoryBase<OrdersGoods> _ordGoodsRepository;
    private readonly RepositoryBase<DeliveryItem> _deliveryItemRepository;
    private readonly RepositoryBase<Delivery> _deliveryRepository;
    private readonly RepositoryBase<UserWallet> _walletRepository;
    private readonly RepositoryBase<SysArea> _areaRepository;
    private readonly RepositoryBase<GoodsGoods> _goodRepository;
    private readonly RepositoryBase<GoodsSize> _godSizeRepository;
    private readonly RepositoryBase<JurUser> _jurUserRepository;
    private readonly RepositoryBase<GoodsPrice> _godPriceRepository;
    private readonly ICapPublisher _capPublisher;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="userRepository"></param>
    /// <param name="orderRepository"></param>
    /// <param name="walletLogRepository"></param>
    /// <param name="ordGoodsRepository"></param>
    /// <param name="deliveryItemRepository"></param>
    /// <param name="deliveryRepository"></param>
    /// <param name="walletRepository"></param>
    /// <param name="areaRepository"></param>
    /// <param name="goodRepository"></param>
    /// <param name="godSizeRepository"></param>
    /// <param name="jurUserRepository"></param>
    /// <param name="godPriceRepository"></param>
    /// <param name="capPublisher"></param>
    public OrdService(
        RepositoryBase<UseUser> userRepository,
        RepositoryBase<Orders> orderRepository,
        RepositoryBase<UserWalletLog> walletLogRepository,
        RepositoryBase<OrdersGoods> ordGoodsRepository,
        RepositoryBase<DeliveryItem> deliveryItemRepository,
        RepositoryBase<Delivery> deliveryRepository,
        RepositoryBase<UserWallet> walletRepository,
        RepositoryBase<SysArea> areaRepository,
        RepositoryBase<GoodsGoods> goodRepository,
        RepositoryBase<GoodsSize> godSizeRepository,
        RepositoryBase<JurUser> jurUserRepository,
        RepositoryBase<GoodsPrice> godPriceRepository,
        ICapPublisher capPublisher)
    {
        _userRepository = userRepository;
        _orderRepository = orderRepository;
        _walletLogRepository = walletLogRepository;
        _ordGoodsRepository = ordGoodsRepository;
        _deliveryItemRepository = deliveryItemRepository;
        _deliveryRepository = deliveryRepository;
        _walletRepository = walletRepository;
        _areaRepository = areaRepository;
        _goodRepository = goodRepository;
        _godSizeRepository = godSizeRepository;
        _jurUserRepository = jurUserRepository;
        _godPriceRepository = godPriceRepository;
        _capPublisher = capPublisher;
    }
    /// <summary>
    /// 订单列表
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public AppResult<PageModel<AOrderListVo>> OrderList(OrderListDto dto)
    {
        var records = 0;
        var data = _orderRepository.Queryable<Orders, UseUser>((t1, t2) => new object[]
            {
                JoinType.Left, t1.UserId == t2.Id
            })
            .WhereIF(dto.UId.HasValue, (t1, t2) => t2.Code == dto.UId.Value)
            .WhereIF(!string.IsNullOrEmpty(dto.Code), (t1, t2) => t1.Code == dto.Code)
            .WhereIF(!string.IsNullOrEmpty(dto.OTele), (t1, t2) => t1.ConsigneePhone == dto.OTele)
            .WhereIF(!string.IsNullOrEmpty(dto.UTele), (t1, t2) => t2.Tele == dto.UTele)
            .WhereIF(dto.Status.HasValue, (t1, t2) => t1.OrderStatus == dto.Status)
            .WhereIF(dto.OType.HasValue, (t1, t2) => t1.OrderType == dto.OType.Value)
            .WhereIF(dto.OrdStartTime.HasValue, (t1, t2) => t1.CreateTime >= dto.OrdStartTime.Value)
            .WhereIF(dto.OrdEndTime.HasValue, (t1, t2) => t1.CreateTime < dto.OrdEndTime.Value)
            .WhereIF(dto.PayStartTime.HasValue, (t1, t2) => t1.PayTime >= dto.PayStartTime.Value)
            .WhereIF(dto.PayEndTime.HasValue, (t1, t2) => t1.PayTime < dto.PayEndTime.Value)
            .WhereIF(dto.OPayChannel.HasValue, (t1, t2) => t1.PayChannel == dto.OPayChannel.Value)
            .WhereIF(!string.IsNullOrEmpty(dto.UName), (t1, t2) => t2.Nickname.Contains(dto.UName))
            .Where((t1, t2) => t1.IsNom == false)
            .OrderBy("t1.CreateTime DESC, t1.Id")
            .Select((t1, t2) => new AOrderListVo()
            {
                Id = t1.Id,
                Code = t1.Code,
                UserId = t2.Code,
                UserName = t2.Nickname,
                ConsigneeName = t1.ConsigneeName,
                ConsigneePhone = t1.ConsigneePhone,
                OrderAmount = t1.OrderAmount,
                OrderStatus = t1.OrderStatus,
                CreateTime = t1.CreateTime,
                PayTime = t1.PayTime,
                DeliveryTime = t1.DeliveryTime,
                OrderType = t1.OrderType,
                PayChannel = t1.PayChannel
            })
            .ToPageList(dto.PageIndex, dto.PageSize, ref records);
        
        foreach (var item in data)
        {
            var ordGoodList = new List<OrdGoodList>();
            var ordGoodInfo = _ordGoodsRepository.Where(x => x.OrdersId == item.Id && x.IsGift == false)
                .Select(x => new OrdGoodList()
                {
                    GImg = x.GoodsImage,
                    GName = x.GoodsName,
                    GSName = x.GoodsSpecName,
                    GCount = x.GoodsQuantity,
                    GPrice = x.GoodsPrice,
                    IsGift = x.IsGift
                }).First();
            if (ordGoodInfo != null)
            {
                ordGoodList.Add(ordGoodInfo);
                var ordGoodGiftInfo = _ordGoodsRepository.Where(x => x.OrdersId == item.Id && x.IsGift == true)
                    .Select(x => new OrdGoodList()
                    {
                        GImg = x.GoodsImage,
                        GName = x.GoodsName,
                        GSName = x.GoodsSpecName,
                        GCount = x.GoodsQuantity,
                        GPrice = x.GoodsPrice,
                        IsGift = x.IsGift
                    }).First();
                if (ordGoodGiftInfo != null)
                    ordGoodList.Add(ordGoodGiftInfo);
                item.OrdGoods = ordGoodList;
            }
        }
        return new PageModel<AOrderListVo>(dto, data, records);
    }

    /// <summary>
    /// 订单详情
    /// </summary>
    /// <param name="oId"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public AppResult<OrderDetailsVo> OrderDetails(long oId)
    {
        var data = _orderRepository.Queryable<Orders, UseUser>((t1, t2) => new object[]
            {
                JoinType.Left, t1.UserId == t2.Id
            })
            .Where((t1, t2) => t1.Id == oId)
            .Select((t1, t2) => new OrderDetailsVo()
            {
                Id = t1.Id,
                Code = t1.Code,
                OrderType = t1.OrderType,
                OrderStatus = t1.OrderStatus,
                CreateTime = t1.CreateTime,
                PayTime = t1.PayTime,
                DeliveryTime = t1.DeliveryTime,
                ConsigneeName = t1.ConsigneeName,
                ConsigneePhone = t1.ConsigneePhone,
                OrderAmount = t1.OrderAmount,
                UserId = t2.Code,
                UserName = t2.Nickname,
                UserTele = t2.Tele,
                UserGrade = t2.Grade
            })
            .First();
        var address = _orderRepository.Where(x => x.Id == oId).First();
        data.ConsigneeAddress = address.ConsigneeProvince + address.ConsigneeProvince + address.ConsigneeCity +
                                address.ConsigneeDistrict + address.ConsigneeTown + address.ConsigneeAddress;
        data.OrdGood = _orderRepository.Queryable<OrdersGoods, DeliveryItem, Delivery>((t1, t2, t3) => new object[]
            {
                JoinType.Left, t1.Id == t2.OrderGoodsId,
                JoinType.Left, t2.DeliveryId == t3.Id
            })
            .Where((t1, t2, t3) => t1.OrdersId == oId)
            .Select((t1, t2, t3) => new OrdGoods()
            {
                GImg = t1.GoodsImage,
                GName = t1.GoodsName,
                GSName = t1.GoodsSpecName,
                GCount = t1.GoodsQuantity,
                GPrice = t1.GoodsPrice,
                IsGift = t1.IsGift,
                LogisticsNo = t3.LogisticsNo
            }).ToList();
        data.OrdCommission = _walletLogRepository.Queryable<UserWalletLog, UseUser>((t1, t2) => new object[]
            {
                JoinType.Left, t1.UserId == t2.Id
            })
            .Where((t1, t2) => t1.SourceOrder == oId)
            .Select((t1, t2) => new OrdCommissionList()
            {
                CId = t2.Code,
                CName = t2.Nickname,
                CTele = t2.Tele,
                Amount = t1.Amount,
                State = t1.State == -1 ? "失败" : t1.State == 1 ? "成功" : "处理中",
                Action = t1.Action == 1 ? "订单付款" :
                    t1.Action == 2 ? "提现" :
                    t1.Action == 3 ? "佣金" :
                    t1.Action == 4 ? "动态分红（服务费）" :
                    t1.Action == 5 ? "定期分红" :
                    t1.Action == 6 ? "后台调整-增加" :
                    t1.Action == 7 ? "后台调整-减少" :
                    t1.Action == 9 ? "用户退款" : "未知状态"
            })
            .ToList();
        return data;
    }

    /// <summary>
    /// 导出订单
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public byte[] ExportToExcel(ExportToExcelDto dto)
    {
        var data = _orderRepository.Queryable<OrdersGoods, Orders, UseUser>((t1, t2, t3) => new object[]
            {
                JoinType.Left, t1.OrdersId == t2.Id && t2.IsNom == false,
                JoinType.Left, t2.UserId == t3.Id
            })
            .WhereIF(dto.UId.HasValue, (t1, t2, t3) => t3.Code == dto.UId.Value)
            .WhereIF(!string.IsNullOrEmpty(dto.Code), (t1, t2, t3) => t2.Code == dto.Code)
            .WhereIF(!string.IsNullOrEmpty(dto.OTele), (t1, t2, t3) => t2.ConsigneePhone == dto.OTele)
            .WhereIF(!string.IsNullOrEmpty(dto.UTele), (t1, t2, t3) => t3.Tele == dto.UTele)
            .WhereIF(dto.Status.HasValue, (t1, t2, t3) => t2.OrderStatus == dto.Status)
            .WhereIF(dto.OType.HasValue, (t1, t2, t3) => t2.OrderType == dto.OType.Value)
            .WhereIF(dto.OrdStartTime.HasValue, (t1, t2, t3) => t2.PayTime > dto.OrdStartTime.Value)
            .WhereIF(dto.OrdEndTime.HasValue, (t1, t2, t3) => t2.PayTime <= dto.OrdEndTime.Value)
            .WhereIF(dto.PayStartTime.HasValue, (t1, t2, t3) => t2.PayTime > dto.PayStartTime.Value)
            .WhereIF(dto.PayEndTime.HasValue, (t1, t2, t3) => t2.PayTime <= dto.PayEndTime.Value)
            .WhereIF(dto.OPayChannel.HasValue, (t1, t2, t3) => t2.PayChannel == dto.OPayChannel.Value)
            .WhereIF(!string.IsNullOrEmpty(dto.UName), (t1, t2, t3) =>t3.Nickname.Contains(dto.UName))
            .Select((t1, t2, t3) => new ToExcelVo()
            {
                OId = t2.Id.ToString(),
                OCode = t2.Code,
                OGId = t1.Id.ToString(),
                UName = t3.Nickname,
                UCode = t3.Code.ToString(),
                OConsigneeName = t2.ConsigneeName,
                OConsigneePhone = t2.ConsigneePhone,
                OConsigneeAddress = SqlFunc.MergeString(t2.ConsigneeProvince, t2.ConsigneeCity, t2.ConsigneeDistrict,
                    t2.ConsigneeTown, t2.ConsigneeAddress),
                OProvince = t2.ConsigneeProvince,
                OCity = t2.ConsigneeCity,
                ODistrict = t2.ConsigneeDistrict,
                OTown = t2.ConsigneeTown,
                OAddress = t2.ConsigneeAddress,
                OGGoodsName = t1.GoodsName,
                OGGoodsSpecName = t1.GoodsSpecName,
                OGGoodsQuantity = t1.GoodsQuantity.ToString(),
                OGGoodsPrice = t1.GoodsPrice.ToString(),
                OGTotalPrice = t1.TotalPrice.ToString(),
                OPayChannel = t2.PayChannel == 1 ? "钱包" :
                    t2.PayChannel == 2 ? "微信" : 
                    t2.PayChannel == 3 ? "线下": "未知",
                OTransactionId = t2.TransactionId,
                OOrderStatus = t2.OrderStatus == -2 ? "已退款" :
                    t2.OrderStatus == -1 ? "已取消" :
                    t2.OrderStatus == 1 ? "未付款" :
                    t2.OrderStatus == 2 ? "已付款" :
                    t2.OrderStatus == 3 ? "已发货" :
                    t2.OrderStatus == 4 ? "已签收" :
                    t2.OrderStatus == 5 ? "已评价" : "未知",
                OCreateTime = t2.CreateTime.ToString(),
                OPayTime = t2.PayTime.ToString(),
                ODeliveryTime = t2.DeliveryTime.ToString(),
                OReceiveTime = t2.ReceiveTime.ToString(),
                OCloseTime = t2.CloseTime.ToString(),
                OGIsGift = t1.IsGift ? "赠品" : "",
                ONote = t2.Note,
                OLogisticsFee = t2.LogisticsFee.ToString(),
                ODiscountAmount = t2.DiscountAmount.ToString()
            })
            .ToList();
        var fieldListKey = dto.FieldList.Select(x => x.Key).ToList();
        var fieldListList = OrderFieldList().Where(x => fieldListKey.Contains(x.Key)).OrderBy(x => x.Sort).ToList();
        DataTable dt = new DataTable();
        foreach (var item in fieldListList)
        {
            dt.Columns.Add(item.Value);
        }
        foreach (var item in data)
        {
            DataRow dataRow = dt.NewRow();
            for (int i = 0; i < fieldListList.Count; i++)
            {
                PropertyValue<ToExcelVo> propertyValue = new PropertyValue<ToExcelVo>(item);
                dataRow[i] = propertyValue.Get(fieldListList[i].Key);
            }
            dt.Rows.Add(dataRow);
        }
        var workBook =  ExcelHelper.DataTableToExcel(dt, "订单");
        using var bookStream = new MemoryStream();
        bookStream.Seek(0, SeekOrigin.Begin);
        workBook.Write(bookStream);
        return bookStream.GetBuffer();
    }

    /// <summary>
    /// 订单导出列
    /// </summary>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public List<OrderFieldListVo> OrderFieldList()
    {
        var orderFieldList = new List<OrderFieldListVo>();
        var fieldListOne = new OrderFieldListVo(){Key = "OId", Value = "订单Id", Sort = 0};
        var fieldListTwo = new OrderFieldListVo(){Key = "OCode", Value = "订单编号", Sort = 1};
        var fieldListThree = new OrderFieldListVo(){Key = "OGId", Value = "订单商品Id", Sort = 2};
        var fieldListFour = new OrderFieldListVo(){Key = "UName", Value = "用户昵称", Sort = 3};
        var fieldListFive = new OrderFieldListVo(){Key = "UCode", Value = "用户Id", Sort = 4};
        var fieldListSix = new OrderFieldListVo(){Key = "OConsigneeName", Value = "收货人姓名", Sort = 5};
        var fieldListSeven = new OrderFieldListVo(){Key = "OConsigneePhone", Value = "收货人手机号", Sort = 6};
        var fieldListEight = new OrderFieldListVo(){Key = "OConsigneeAddress", Value = "收货人地址", Sort = 7};
        var fieldListNine = new OrderFieldListVo(){Key = "OProvince", Value = "收货省", Sort = 8};
        var fieldListTen = new OrderFieldListVo(){Key = "OCity", Value = "收货市", Sort = 9};
        var fieldListEleven = new OrderFieldListVo(){Key = "ODistrict", Value = "收货区/县", Sort = 10};
        var fieldListTwelve = new OrderFieldListVo(){Key = "OTown", Value = "收货乡/镇/街道", Sort = 11};
        var fieldListThirteen = new OrderFieldListVo(){Key = "OAddress", Value = "收货地址详细", Sort = 12};
        var fieldListFourteen = new OrderFieldListVo(){Key = "OGGoodsName", Value = "商品名", Sort = 13};
        var fieldListFifteen = new OrderFieldListVo(){Key = "OGGoodsSpecName", Value = "规格名", Sort = 14};
        var fieldListSixteen = new OrderFieldListVo(){Key = "OGGoodsQuantity", Value = "商品数量", Sort = 15};
        var fieldListSeventeen = new OrderFieldListVo(){Key = "OGGoodsPrice", Value = "商品单价", Sort = 16};
        var fieldListEighteen = new OrderFieldListVo(){Key = "OGTotalPrice", Value = "商品总价", Sort = 17};
        var fieldListNineteen = new OrderFieldListVo(){Key = "OPayChannel", Value = "支付方式", Sort = 18};
        var fieldListTwenty = new OrderFieldListVo(){Key = "OTransactionId", Value = "微信支付订单号", Sort = 19};
        var fieldListTwentyOne = new OrderFieldListVo(){Key = "OOrderStatus", Value = "订单状态", Sort = 20};
        var fieldListTwentyTwo = new OrderFieldListVo(){Key = "OCreateTime", Value = "下单时间", Sort = 21};
        var fieldListTwentyThree = new OrderFieldListVo(){Key = "OPayTime", Value = "付款时间", Sort = 22};
        var fieldListTwentyFour = new OrderFieldListVo(){Key = "ODeliveryTime", Value = "发货时间", Sort = 23};
        var fieldListTwentyFive = new OrderFieldListVo(){Key = "OReceiveTime", Value = "收货时间", Sort = 24};
        var fieldListTwentySix = new OrderFieldListVo(){Key = "OCloseTime", Value = "取消/超期时间", Sort = 25};
        var fieldListTwentySeven = new OrderFieldListVo(){Key = "OGIsGift", Value = "是否赠品", Sort = 26};
        var fieldListTwentyEight = new OrderFieldListVo(){Key = "ONote", Value = "买家备注", Sort = 27};
        var fieldListTwentyNine = new OrderFieldListVo(){Key = "OLogisticsFee", Value = "物流费用", Sort = 28};
        var fieldListThirty = new OrderFieldListVo(){Key = "ODiscountAmount", Value = "优惠金额", Sort = 29};
        orderFieldList.Add(fieldListOne);
        orderFieldList.Add(fieldListTwo);
        orderFieldList.Add(fieldListThree);
        orderFieldList.Add(fieldListFour);
        orderFieldList.Add(fieldListFive);
        orderFieldList.Add(fieldListSix);
        orderFieldList.Add(fieldListSeven);
        orderFieldList.Add(fieldListEight);
        orderFieldList.Add(fieldListNine);
        orderFieldList.Add(fieldListTen);
        orderFieldList.Add(fieldListEleven);
        orderFieldList.Add(fieldListTwelve);
        orderFieldList.Add(fieldListThirteen);
        orderFieldList.Add(fieldListFourteen);
        orderFieldList.Add(fieldListFifteen);
        orderFieldList.Add(fieldListSixteen);
        orderFieldList.Add(fieldListSeventeen);
        orderFieldList.Add(fieldListEighteen);
        orderFieldList.Add(fieldListNineteen);
        orderFieldList.Add(fieldListTwenty);
        orderFieldList.Add(fieldListTwentyOne);
        orderFieldList.Add(fieldListTwentyTwo);
        orderFieldList.Add(fieldListTwentyThree);
        orderFieldList.Add(fieldListTwentyFour);
        orderFieldList.Add(fieldListTwentyFive);
        orderFieldList.Add(fieldListTwentySix);
        orderFieldList.Add(fieldListTwentySeven);
        orderFieldList.Add(fieldListTwentyEight);
        orderFieldList.Add(fieldListTwentyNine);
        orderFieldList.Add(fieldListThirty);
        return orderFieldList;
    }

    /// <summary>
    /// 计算行家业绩
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public byte[] ExportPerformance(ExportPerformanceDto dto)
    {
        var ordData = _orderRepository.Queryable<Orders, UseUser>((t1, t2) => new object[]
            {
                JoinType.Left, t1.UserId == t2.Id
            })
            .Where((t1, t2) => t1.OrderStatus >= 2 && t1.PayTime >= dto.StartTime && t1.PayTime < dto.EndTime)
            .Select((t1, t2) => new OrdDataVo()
            {
                Id = t2.Id,
                Code = t2.Code,
                Name = t2.Nickname,
                Grade = t2.Grade,
                Point = t1.Point
            })
            .ToList();
        var hj = new List<OrdDataVo>();
        var fhj = new List<OrdDataVo>();
        foreach (var item in ordData)
        {
            if (item.Grade == 3)
                hj.Add(item);
            else
                fhj.Add(item);
        }

        foreach (var item in fhj)
        {
            var dd = _userRepository.Queryable<UseUserRelation, UseUser>((t1, t2) => new object[]
                {
                    JoinType.Left, t1.Ancestor == t2.Id
                })
                .Where((t1, t2) => t1.Descendant == item.Id && t2.Grade == 3)
                .OrderBy((t1, t2) => t1.Level)
                .Select((t1, t2) => new SupVo()
                {
                    Id = t2.Id,
                    Code = t2.Code,
                    Name = t2.Nickname,
                    Level = t1.Level
                })
                .ToPageList(1, 2);
            if (dd.Count == 1)
            {
                item.OneHjId = dd[0].Id;
                item.OneHjCode = dd[0].Code;
                item.OneHjName = dd[0].Name;
                item.OnePerfor = item.Point * 0.5M;
            }
            if (dd.Count == 2)
            {
                item.OneHjId = dd[0].Id;
                item.OneHjCode = dd[0].Code;
                item.OneHjName = dd[0].Name;
                item.OnePerfor = item.Point * 0.5M;
                item.TwoHjId = dd[1].Id;
                item.TwoHjCode = dd[1].Code;
                item.TwoHjName = dd[1].Name;
                item.TwoPerfor = item.Point * 0.2M;
            }
        }

        foreach (var item in hj)
        {
            var dd = _userRepository.Queryable<UseUserRelation, UseUser>((t1, t2) => new object[]
                {
                    JoinType.Left, t1.Ancestor == t2.Id
                })
                .Where((t1, t2) => t1.Descendant == item.Id && t2.Grade == 3)
                .OrderBy((t1, t2) => t1.Level)
                .Select((t1, t2) => new SupVo()
                {
                    Id = t2.Id,
                    Code = t2.Code,
                    Name = t2.Nickname,
                    Level = t1.Level
                })
                .First();
            if (dd == null)
            {
                item.OneHjId = item.Id;
                item.OneHjCode = item.Code;
                item.OneHjName = item.Name;
                item.OnePerfor = item.Point * 0.5M;
            }
            if (dd != null)
            {
                item.OneHjId = item.Id;
                item.OneHjCode = item.Code;
                item.OneHjName = item.Name;
                item.OnePerfor = item.Point * 0.5M;
                item.TwoHjId = dd.Id;
                item.TwoHjCode = dd.Code;
                item.TwoHjName = dd.Name;
                item.TwoPerfor = item.Point * 0.2M;
            }
        }
        fhj.AddRange(hj);
        DataTable dt = new DataTable();
        dt.Columns.Add("下单人Id");
        dt.Columns.Add("下单人Code");
        dt.Columns.Add("下单人昵称");
        dt.Columns.Add("下单人级别");
        dt.Columns.Add("单量");
        dt.Columns.Add("一级行家Id");
        dt.Columns.Add("一级行家Code");
        dt.Columns.Add("一级行家昵称");
        dt.Columns.Add("一级行家业绩");
        dt.Columns.Add("二级行家Id");
        dt.Columns.Add("二级行家Code");
        dt.Columns.Add("二级行家昵称");
        dt.Columns.Add("二级行家业绩");

        foreach (var item in fhj)
        {
            DataRow dataRow = dt.NewRow();
            dataRow[0] = item.Id;
            dataRow[1] = item.Code;
            dataRow[2] = item.Name;
            dataRow[3] = item.Grade;
            dataRow[4] = item.Point;
            dataRow[5] = item.OneHjId;
            dataRow[6] = item.OneHjCode;
            dataRow[7] = item.OneHjName;
            dataRow[8] = item.OnePerfor;
            dataRow[9] = item.TwoHjId;
            dataRow[10] = item.TwoHjCode;
            dataRow[11] = item.TwoHjName;
            dataRow[12] = item.TwoPerfor;
            dt.Rows.Add(dataRow);
        }
        var workBook =  ExcelHelper.DataTableToExcel(dt, "行家业绩");
        using var bookStream = new MemoryStream();
        bookStream.Seek(0, SeekOrigin.Begin);
        workBook.Write(bookStream);
        return bookStream.GetBuffer();
    }

    /// <summary>
    /// 订单商品
    /// </summary>
    /// <param name="oId"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public AppResult<List<OrdGoodsVo>> OrdGoods(long oId)
    {
        var data = _ordGoodsRepository.Where(x => x.OrdersId == oId)
            .Select(x => new OrdGoodsVo()
            {
                OId = x.OrdersId,
                OSId = x.Id,
                OSName = x.GoodsName
            })
            .ToList();
        return data;
    }

    /// <summary>
    /// 标记发货
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<AppResult> Shipments(List<ShipmentsDto> dto)
    {
        List<DeliveryItem> deliveryItemList = new List<DeliveryItem>();
        var oId = dto.Select(x => x.OId).First();
        foreach (var item in dto)
        {
            var deliveryInfo = new Delivery()
            {
                LogisticsCompany = item.LName,
                LogisticsCompanyCode = item.LName,
                LogisticsNo = item.LNo,
                SendTime = DateTime.Now
            };
            var deliveryId = await _deliveryRepository.InsertReturnIdentityAsync(deliveryInfo);
            var deliveryItem = new DeliveryItem()
            {
                OrderId = item.OId,
                OrderGoodsId = item.OSId,
                DeliveryId = deliveryId
            };
            deliveryItemList.Add(deliveryItem);
        }

        var ordInfo = _orderRepository.Where(x => x.Id == oId).First();
        ordInfo.OrderStatus = 3 ;
        ordInfo.DeliveryTime = DateTime.Now;
        await _deliveryItemRepository.InsertRangeAsync(deliveryItemList);
        await _orderRepository.UpdateAsync(ordInfo);
        return new AppResult();
    }

    /// <summary>
    /// 取消订单
    /// </summary>
    /// <param name="oId"></param>
    /// <param name="userContextId"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public AppResult CancelOrd(long oId, long userContextId)
    {
        var ordInfo = _orderRepository.Where(x => x.Id == oId).First();
        if (ordInfo == null)
            return Problem("订单不存在");
        if (ordInfo.OrderStatus == -2)
            return Problem("订单已取消");
        if (ordInfo.OrderStatus == 1)
            return Problem("未付款订单无法取消");
        if (ordInfo.OrderStatus == 2 || ordInfo.OrderStatus == 3)
        {
            var wallet = _walletLogRepository.Where(x => x.SourceOrder == oId && x.State == 0).ToList();
            foreach (var item in wallet)
            {
                var useWallet = _walletRepository.Where(x => x.UserId == item.UserId).First();
                useWallet.Brokerage -= item.Amount;
                useWallet.Surplus -= item.Amount;
                _walletRepository.Update(useWallet);
                item.State = -1;
                item.FinishTime = DateTime.Now;
            }

            _walletLogRepository.UpdateRange(wallet);
        }
        var ordWallet = _walletLogRepository.Where(x => x.SourceOrder == oId && x.State == 1 && x.UserId == ordInfo.UserId && x.Action == 1).First();
        if (ordWallet != null)
        {
            var useWalletLog = new UserWalletLog()
            {
                UserId = ordInfo.UserId,
                SourceOrder = ordInfo.Id,
                Action = (int)GlobalEnum.UserWalletSourceTypes.Refund,
                State = 1,
                Title = $"订单：{ordInfo.Code},取消订单，支付金额退还",
                Amount = ordWallet.Amount,
                CreateTime = DateTime.Now,
                FinishTime = DateTime.Now
            };
            var useWallet = _walletRepository.Where(x => x.UserId == ordWallet.UserId).First();
            useWallet.Balance += useWalletLog.Amount;
            _walletRepository.Update(useWallet);
            _walletLogRepository.Insert(useWalletLog);
        }

        ordInfo.OrderStatus = -2;
        ordInfo.CloseTime = DateTime.Now;
        _orderRepository.Update(ordInfo);
        return new AppResult();
    }

    /// <summary>
    /// 地址库
    /// </summary>
    /// <param name="dto"></param>
    /// <returns></returns>
    public AppResult<List<AddAreaVo>> AddArea(string dto)
    {
        var data = _areaRepository.Where(x => x.Parent_Code == dto)
            .OrderBy(x => x.Code)
            .Select(x => new AddAreaVo()
            {
                Code = x.Code,
                Name = x.Name
            })
            .ToList();
        return data;
    }

    /// <summary>
    /// 商品列表
    /// </summary>
    /// <param name="gName"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public AppResult<List<GoodsListVo>> GoodsList(string? gName)
    {
        var data = _goodRepository.Includes(x => x.Size)
            .Where(x => x.Valid == true && x.Saleable == true && x.Type == 1)
            .WhereIF(!string.IsNullOrEmpty(gName), x => x.Name.Contains(gName))
            .ToList(x => new GoodsListVo()
            {
                GId = x.Id,
                GName = x.Name,
                Spec = x.Spc,
                GoodSize = x.Size.Select(a => new GoodSize { GSId = a.Id, GSName = a.Name }).ToList()
            })
            .ToList();
        return data;
    }

    /// <summary>
    /// 创建订单
    /// </summary>
    /// <param name="dto"></param>
    /// <param name="userContextId"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<AppResult> AddOrder(AddOrderDto dto, long userContextId)
    {
        var userInfo = _userRepository.Where(x => x.Id == dto.UserId).First();
        if (userInfo == null)
            return Problem("用户不存在");
        var goodsInfo = _goodRepository.Where(x => x.Id == dto.GoodsId && x.Valid == true && x.Saleable == true && x.Type == 1)
            .First();
        if (goodsInfo == null)
            return Problem("商品信息有误");
        var specInfo = _godSizeRepository.Where(x => x.Id == dto.GoodsSpecId && x.GoodsId == dto.GoodsId).First();
        if (specInfo == null)
            return Problem("商品规格信息错误");
        var specPrice = _godPriceRepository.Where(x => x.Goods == dto.GoodsId && x.Size == dto.GoodsSpecId).First();
        if (specPrice == null)
            return Problem("商品价格错误");
        if (dto.GoodsNum <= 0)
            return Problem("商品数量不可小于0");
        if (dto.OrderAmount <= 0)
            return Problem("支付金额不可小于0.00");
        var jurUser = _jurUserRepository.Where(x => x.Id == userContextId).First();
        if (jurUser == null)
            return Problem("管理员账号有误");
        var orderItem = new OrdersGoods
        {
            GoodsId = goodsInfo.Id,
            GoodsName = goodsInfo.Name,
            GoodsSpecId = specInfo.Id,
            GoodsSpecName = specInfo.Name,
            GoodsCode = specInfo.Code,
            GoodsPrice = userInfo.Grade switch
            {
                1 => specPrice.OnePrice,
                2 => specPrice.TwoPrice,
                3 => specPrice.ThreePrice,
                _ => specPrice.Price,
            },
            GoodsQuantity = dto.GoodsNum,
            GoodsImage = specInfo.Thumbnail
        };
        orderItem.TotalPrice = orderItem.GoodsPrice * orderItem.GoodsQuantity;
        var point = specInfo.Point * dto.GoodsNum;
        try
        {
            _orderRepository.BeginTran();
            var order = new Orders()
            {
                Code = CreateOrderCode(),
                UserId = userInfo.Id,
                ConsigneeName = dto.ConsigneeName,
                ConsigneePhone = dto.ConsigneePhone,
                ConsigneeProvince = dto.ConsigneeProvince,
                ConsigneeCity = dto.ConsigneeCity,
                ConsigneeDistrict = dto.ConsigneeDistrict,
                ConsigneeAddress = dto.ConsigneeAddress,
                GoodsAmount = orderItem.TotalPrice,
                OrderAmount = dto.OrderAmount,
                OrderType = 3,
                OrderStatus = 2,
                PayChannel = 3,
                AdminTime = DateTime.Now,
                AdminId = userContextId,
                PayTime = DateTime.Now,
                Point = point,
                IsBrokerage = dto.IsCommission,
                IsAdmin = true
            };
            var orderId = await _orderRepository.InsertReturnBigIdentityAsync(order);
            orderItem.OrdersId = orderId;
            await _orderRepository.Change<OrdersGoods>().InsertAsync(orderItem);
            if (dto.IsCommission)
                await _capPublisher.PublishAsync("Order.Payment", orderId);
            await _capPublisher.PublishAsync("Order.Push", orderId);
            _orderRepository.CommitTran();
            return new AppResult();
        }
        catch (Exception)
        {
            _orderRepository.RollbackTran();
            return Problem("下单失败");
        }
    }
    
    /// <summary>
    /// 订单Code生成
    /// </summary>
    /// <returns></returns>
    private static string CreateOrderCode()
    {
        Random random = new Random();
        string strRandom = random.Next(10000, 99999).ToString();
        string code = $"DD{DateTime.Now.ToString("yyyyMMddHHmmssffff")}{strRandom}";
        return code;
    }
}